package xj.graph2d.template;

import java.util.Map;

import xj.graph2d.ArrowAttr;
import xj.graph2d.DrawAttr;
import xj.graph2d.DrawShape;
import xj.graph2d.EllipseShape;
import xj.graph2d.LineShape;
import xj.graph2d.OpenShape;
import xj.graph2d.GraphEdgeBase;
import xj.graph2d.shapes.CircleShape;
import xj.graph2d.shapes.CubicCurveShape;
import xj.graph2d.shapes.PolyCurveShape;
import xj.graph2d.shapes.OrthogonalLineShape;
import xj.graph2d.shapes.QuadCurveShape;
import xj.graph2d.shapes.GraphEdgeShape;
import xj.graph2d.shapes.RectangularShape;
import xj.graph2d.shapes.RoundRectangleShape;
import xj.graph2d.shapes.ShapeConstants;

public class FlowGraphTemplate extends Template {

  static int[] shapesNorth = { 
    ShapeConstants.BOX_SHAPE,
    ShapeConstants.DIAMOND_SHAPE, 
    ShapeConstants.PARALLELOGRAM_SHAPE,
    ShapeConstants.HEXAGON_SHAPE, 
    ShapeConstants.OCTAGON_SHAPE,
  };

  static String[] namesNorth = { 
    "Rectangle", 
    "Diamond", 
    "Parallelogram",
    "Hexagon", 
    "Octagon",
  };

  static int[] shapesAll = { 
    ShapeConstants.TRIANGLE_SHAPE,
    ShapeConstants.RIGHT_TRIANGLE_SHAPE, 
    ShapeConstants.TRAPEZOID_SHAPE,
    ShapeConstants.HOUSE_SHAPE, 
    ShapeConstants.CAVE_SHAPE,
    ShapeConstants.PENTAGON_SHAPE,
  };

  static String[] namesAll = { 
    "Triangle", 
    "RightTriangle", 
    "Trapezoid",
    "House", 
    "Cave", 
    "Pentagon",
  };

  static String[] flowEdgeShapeNames = {
    "Flow-Shape1", "Flow-Shape2", "Flow-Shape3", "Flow-Shape4", "Flow-Shape5", 
  };

  public static String getSuffix(int dir) {
    switch (dir) {
    case ShapeConstants.NORTH:
      return "north";
    case ShapeConstants.EAST:
      return "east";
    case ShapeConstants.SOUTH:
      return "south";
    case ShapeConstants.WEST:
      return "west";
    }
    return null;
  }

  public FlowGraphTemplate() {
  }

  public void initTools() {
    String[] flowTemp = { ".Line", ".Curve1", ".Curve2", ".VLine", ".HLine", 
			  ".PolyLine1", ".PolyLine2" };
    for (int i = 0; i < flowTemp.length; i++) { 
      addEdgeToolNames(name + flowTemp[i], flowEdgeShapeNames);
    }

  }

  @Override
  public void makeTemplate(Map iconMap) {
    DrawShape shape;

    shape = new CircleShape(50, 50, 50);
    add(new TemplateToolButton("Circle", setAttr(shape), 36, 30, false, true));

    shape = new EllipseShape(0, 0, 100, 60);
    add(new TemplateToolButton("Ellipse", setAttr(shape), 36, 30, false, true));

    shape = new RoundRectangleShape(0, 0, 100, 60);
    add(new TemplateToolButton("RoundRectangle", setAttr(shape), 36, 30, false, true));

    int i;
    for (i = 0; i < shapesNorth.length; i++) {
      RectangularShape rshape = new RectangularShape(shapesNorth[i],
	  ShapeConstants.NORTH, 0, 0, 100, 60);
      add(new TemplateToolButton(namesNorth[i], setAttr(rshape), 36, 30, false, true));
    }

    for (i = 0; i < shapesAll.length; i++) {
      for (int j = ShapeConstants.NORTH; j <= ShapeConstants.WEST; j++) {
	RectangularShape rshape = new RectangularShape(shapesAll[i], j, 0, 0, 100, 60);
	add(new TemplateToolButton(namesAll[i] + "." + getSuffix(j), setAttr(rshape), 
				   36, 30, false, true));
      }
    }

    //LineShape line = new LineShape(0, 0, 100, 100);
    GraphEdgeShape line = new GraphEdgeShape(0, 0, 100, 100);
    add(new TemplateToolButton("Line", setAttr(line), 36, 24, false, true));

    //QuadCurveShape qcurve = new QuadCurveShape(0, 70, 100, 30, 30, 0);
    GraphEdgeShape qcurve = new GraphEdgeShape(0, 70, 100, 30, 30, 0);
    add(new TemplateToolButton("Curve1", setAttr(qcurve), 36, 24, false, true));
    //CubicCurveShape curve = new CubicCurveShape(0, 70, 100, 30, 20, 20, 80, 80);
    GraphEdgeShape curve = new GraphEdgeShape(0, 70, 100, 30, 20, 20, 80, 80);
    add(new TemplateToolButton("Curve2", setAttr(curve), 36, 24, false, true));

    //OrthogonalLineShape oline = new OrthogonalLineShape(false, 60, 0);
    GraphEdgeShape oline = new GraphEdgeShape(false, 60, 0);
    oline.addPoint(0, 50);
    oline.addPoint(60, 100);
    oline.calculateBounds();
    add(new TemplateToolButton("VLine", setAttr(oline), 36, 24, false, true));

    //oline = new OrthogonalLineShape(0, 50);
    oline = new GraphEdgeShape(true, 0, 50);
    oline.addPoint(50, 0);
    oline.addPoint(100, 50);
    oline.calculateBounds();
    add(new TemplateToolButton("HLine", setAttr(oline), 36, 24, false, true));

    //oline = new OrthogonalLineShape(0, 80);
    oline = new GraphEdgeShape(true, 0, 80);
    oline.addPoint(100, 20);
    oline.calculateBounds();
    add(new TemplateToolButton("PolyLine1", setAttr(oline), 36, 24, false, true));

    //oline = new OrthogonalLineShape(false, 0, 80);
    oline = new GraphEdgeShape(false, 0, 80);
    oline.addPoint(80, 0);
    oline.calculateBounds();
    add(new TemplateToolButton("PolyLine2", setAttr(oline), 36, 24, false, true));

    // System.out.println("FlowGraphTemplate: oline=" + oline);
    makeNodeEdgePopupTemplates();
    makeEdgeShapeTemplates();
  }

  protected void makeNodeEdgePopupTemplates() { 

  }

  protected void makeEdgeShapeTemplates() { 
    // flow edge shape template 
    LineShape line1 = new LineShape(0, 20, 50, 20);
    addFlowShapeTemplate("Flow-Shape1", line1, FLOW_COLOR, 25, 10);

    QuadCurveShape qcurve1 = new QuadCurveShape(0, 24, 48, 0, 12, 0);
    addFlowShapeTemplate("Flow-Shape2", qcurve1, FLOW_COLOR, 25, 10);
    
    CubicCurveShape curve1 = new CubicCurveShape(0, 24, 48, 24, 12, 0, 36, 0);
    addFlowShapeTemplate("Flow-Shape3", curve1, FLOW_COLOR, 25, 10);

    OrthogonalLineShape oline = new OrthogonalLineShape(0, 50);
    oline.addPoint(50, 0);
    oline.addPoint(100, 50);
    oline.setRoundCorner(true);
    oline.calculateBounds();
    addFlowShapeTemplate("Flow-Shape4", oline, FLOW_COLOR, 25, 10);

    PolyCurveShape pcurve = new PolyCurveShape(0, 0);
    pcurve.addPoint(30, 40);
    pcurve.addPoint(70, 0);
    pcurve.addPoint(100, 40);
    pcurve.adjustControlPoints();
    pcurve.calculateBounds();
    addFlowShapeTemplate("Flow-Shape5", pcurve, FLOW_COLOR, 25, 10);
  }

  protected DrawShape setAttr(DrawShape shape) {
    if (shape != null) {
      DrawAttr attr = new DrawAttr();
      shape.setDrawAttr(attr);
      if (shape instanceof OpenShape) {
	OpenShape oshape = (OpenShape) shape;
	ArrowAttr headArrowAttr = new ArrowAttr();
	headArrowAttr.setType(ArrowAttr.ArrowType.FilledTriangle);
	headArrowAttr.setSize(12);
	oshape.addArrows(headArrowAttr, null);
	setPenColor(shape, NODE_FG);
      } else {
	shape.setAllowRotation(false);
	shape.setSymetricResize(false);
	setNodeAttr(shape);
	setNodeColor(shape, NODE_FG, NODE_BG);
      }
    }
    return shape;
  }

  protected void addFlowShapeTemplate(String name, 
				      GraphEdgeBase edge, 
				      String colorkey,
				      int iconWidth, int iconHeight) { 
    if (name != null && 
	edge != null) { 
      setAttr(edge);
      if (colorkey != null) {
	setPenColor(edge, colorkey);
      }
      addEdgeShapeTemplate(name, edge, iconWidth, iconHeight);
    }
  }

  public static final String NODE_FG = "template.FlowGraph.fg";
  public static final String NODE_BG = "template.FlowGraph.bg";
  public static final String FLOW_COLOR = "template.FlowGraph.flow.color";

}
